package com.example.util.tableshard;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public class TableShardingAlgorithm {

    /**
     * 基于Hash取模的分表算法
     * @param serialNumber 串号
     * @return 表名
     */
    public static String getTableByHash(String serialNumber,String tableSuffix,Integer tableCount) {
        if (serialNumber == null || serialNumber.trim().isEmpty()) {
            throw new IllegalArgumentException("串号不能为空");
        }

        // 计算Hash值
        int hash = getStableHash(serialNumber);

        // 取模得到表索引 (0-9)
        int tableIndex = Math.abs(hash) % tableCount;

        return buildTableName(tableSuffix,tableIndex);
    }


    public static Integer getTableIndexByHash(String serialNumber,Integer tableCount) {
        if (serialNumber == null || serialNumber.trim().isEmpty()) {
            throw new IllegalArgumentException("串号不能为空");
        }

        // 计算Hash值
        int hash = getStableHash(serialNumber);

        // 取模得到表索引 (0-9)
        int tableIndex = Math.abs(hash) % tableCount;

        return tableIndex;
    }



    /**
     * 一致性Hash分表算法（减少数据迁移）
     * @param serialNumber 串号
     * @return 表名
     */
    public static String getTableByConsistentHash(String serialNumber,String tableSuffix,int tableCount) {
        if (serialNumber == null || serialNumber.trim().isEmpty()) {
            throw new IllegalArgumentException("串号不能为空");
        }

        // 使用MD5获得更均匀的分布
        long hash = getMD5Hash(serialNumber);

        // 取模得到表索引
        int tableIndex = (int) (Math.abs(hash) % tableCount);

        return buildTableName(tableSuffix,tableIndex);
    }

    public static Integer getTableIndexByConsistentHash(String serialNumber,int tableCount) {
        if (serialNumber == null || serialNumber.trim().isEmpty()) {
            throw new IllegalArgumentException("串号不能为空");
        }

        // 使用MD5获得更均匀的分布
        long hash = getMD5Hash(serialNumber);

        // 取模得到表索引
        int tableIndex = (int) (Math.abs(hash) % tableCount);

        return tableIndex;
    }

    /**
     * 稳定的Hash算法
     */
    private static int getStableHash(String str) {
        int hash = 0;
        for (int i = 0; i < str.length(); i++) {
            hash = 31 * hash + str.charAt(i);
        }
        return hash;
    }

    /**
     * MD5 Hash算法（更均匀的分布）
     */
    private static long getMD5Hash(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(str.getBytes());

            // 取前8字节转换为long
            long hash = 0;
            for (int i = 0; i < 8; i++) {
                hash = (hash << 8) | (digest[i] & 0xFF);
            }
            return hash;
        } catch (NoSuchAlgorithmException e) {
            // 降级到稳定Hash
            return getStableHash(str);
        }
    }

    /**
     * 构建表名
     */
    private static String buildTableName(String tableSuffix,int tableIndex) {
        return tableSuffix + tableIndex;
    }

    /**
     * 获取所有表名
     */
    public static String[] getAllTableNames(String tableSuffix,int tableCount) {
        String[] tables = new String[tableCount];
        for (int i = 0; i < tableCount; i++) {
            tables[i] = buildTableName(tableSuffix,tableCount);
        }
        return tables;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100 ; i++) {
            String table=getTableByHash("user"+i,"table_",4);
            System.out.println(table);
        }
    }

}
